#include "sxdriver.h"
#include "sxio.h"

#include "common.h"

extern void _putc(unsigned char c);


#define SPRINTF(a) print_str(a)


/*****************************************************************************************************
** Name:      Msdelay()
** Function:  time delay
*****************************************************************************************************/

#define ACK			0
#define NACK			1

#define	DELAY_TIME	6
//#define	DELAY_TIME	100

void delay(UINT16 t) 
{ 
	while(t!=0) 
	  t--; 
} 



/****************************************************************
*     _____      _____________              ______________          ___________
* SCL      |____|             |____________|              .....____|
*
*     |Start|   |<--Read-->| |<--Write--->|                          |*STOP*|
* SDA ___      ________________             ______________              ________
*        |____|                MMMMMMMMMMMMM              .....________|
*
*
*****************************************************************/
// SCL:0, SDA:0
// SCL:H--H--L
// SDA:H--L--L
void Start(void)               
{ 
  SCL=1; 
  
  SDA=1; 
  delay(DELAY_TIME); 
  SDA=0; 
  delay(DELAY_TIME); 
  
  SCL=0; 
  delay(DELAY_TIME); 
}


// SCL:H--H--H
// SDA:L--H--H
void Stop(void)              
{
	SDA=0; 
	SCL=1; 
	delay(DELAY_TIME); 
	SDA=1; 
	delay(DELAY_TIME); 
	SCL=0; 
	delay(DELAY_TIME);
	SCL=1; 

}


// 0:ACK, 1:NACK(last byte)
void Send_ACK(UINT8 ack)
{
	SCL = 0;
	SDA = ack;
	//if(ack)		
	//	SDA = 0;
	//else
	//	SDA = 1;
	
	delay(DELAY_TIME); 
	SCL=1; 
	delay(DELAY_TIME); 
	SCL=0; 
	delay(DELAY_TIME); 
}




 

UINT8 Check_ACK(void) 
{ 
	UINT8	cnt;
	
	SDA = 1; 
	SCL = 1; 
	delay(DELAY_TIME); 
	
	for(cnt = 0; cnt< 100; cnt++)
	{
		if( SDA == 0)
			break;		// ack getted~
		delay(3); 	
	}

	SCL = 0; 
	delay(DELAY_TIME); 
	
	if (cnt >=100) // over time!
	  return 0; 

	return 1; 
} 






// SCL: Hi-->Lo == begin to write
void Write_Byte(UINT8 dat)
{
	UINT8 i; 
	
	for (i = 0; i < 8; i++)
	{
		if ((dat<<i) & 0x80) {
		  SDA = 1; 
		}
		else {
	     	  SDA = 0;
		}
		SCL = 1;
		delay(DELAY_TIME);
		SCL = 0;
		delay(DELAY_TIME);
	}

}


UINT8 Write_Byte_Check(UINT8 dat)
{
	Write_Byte(dat);
	if (!Check_ACK()) 
	{ 
		Stop();
		SPRINTF(("ACK err\n"));	
		return 0; 
	}
	//SPRINTF(("ACK OK!\n"));	
	return 1;
}





//	MSB->LSB
// SCL: Lo-->Hi == begin to read
UINT8 Read_Byte(void)
{
    UINT8 Data1=0x00;
    UINT8 j;

	SCL = 0;
	delay(10);
	SDA = 1;	// ready for input
  
	for (j = 0; j < 8; j++) 
	{ 
		delay(DELAY_TIME);
		SCL = 0;	
		delay(DELAY_TIME);
		SCL = 1;	// valid data
		delay(DELAY_TIME);
		
		Data1 <<= 1;
		
		if(SDA){
			Data1 += 1;
		}
	} 
	
	SCL = 0;

    return Data1;
}
 
/************************************************************************************************************
** Name: I2C_Write_1byte                         
** Funcation:write a data to a desired            
**           register through i2c bus 
** Description: Slave---------device address
**              Regis_Addr----register address
*************************************************************************************************************/
UINT8 I2C_Write_1byte(UINT8 Slave,UINT8 Regis_Addr,UINT8 dat)
{
    Start();
	
	if(Write_Byte_Check(Slave)==0)
		return 0;

	if(Write_Byte_Check(Regis_Addr)==0)
		return 0;

	if(Write_Byte_Check(dat)==0)
		return 0;

    Stop();
	
    return 1;
}
 	   
/***********************************************************************************************************
** Name: I2C_Read_1byte                          
** Function: Read a data from a desired register 
**           through i2c bus 
** Description: Slave---------device address
**              Regis_Addr----register address
************************************************************************************************************/
UINT8 I2C_Read_1byte(UINT8 Slave,UINT8 Regis_Addr, UINT8 *buff)
{ 
    UINT8 dat = 0x00;
    UINT8 temp;
    temp =Slave | 0x01;

        Start();

	//print_strhex("slave", Slave);
	//print_strhex("Regis_Addr", Regis_Addr);
	//print_strhex("temp", temp);	

	if(Write_Byte_Check(Slave)==0)
		return 0;

	if(Write_Byte_Check(Regis_Addr)==0)
		return 0;

	Stop();
	Start();

	if(Write_Byte_Check(temp)==0)
		return 0;

	*buff = Read_Byte();
	Send_ACK(NACK);

    Stop();

    return 1;
}

  /***********************************************************************************************************
  ** Name: I2C_Read_nbyte							
  ** Function: Read n data from a desired register	
  **		   through i2c bus 
  ** Description: Slave---------device address
  **			  Regis_Addr----register address
  ************************************************************************************************************/
  UINT8 I2C_Read_nbyte(UINT8 Slave,UINT8 Regis_Addr, UINT8 *buf, UINT8 n)
  { 
    UINT8 Data=0x00;
    UINT8 i;

    Start();
	if(Write_Byte_Check(Slave)==0)
		return 0;
	if(Write_Byte_Check(Regis_Addr)==0)
		return 0;
	
	Stop();

	// restart
	Start();
	if(Write_Byte_Check(Slave|0x01)==0)
		return 0;
	
	for(i=0; i<n-1; i++) {
		buf[i] = Read_Byte();
		Send_ACK(ACK);
	}
	buf[i] = Read_Byte();
	Send_ACK(NACK);

    Stop();
    return 1;
}



  /***********************************************************************************************************
	** Name: I2C_Write_nbyte				
	** Function: Write n bytes data to register 
	**			 through i2c bus 
	** Description: Slave---------device address
	**				Regis_Addr----register address
	************************************************************************************************************/
UINT8 I2C_Write_nbyte(UINT8 Slave,UINT8 Regis_Addr, UINT8 *buf, UINT8 n)
{ 
    UINT8 temp;
	UINT8 i;
    temp=Slave;


    Start();
	if(Write_Byte_Check(Slave)==0)
		return 0;
	if(Write_Byte_Check(Regis_Addr)==0)
		return 0;
	
    for(i=0; i<n; i++) {
		if(Write_Byte_Check(buf[i])==0)
			return 0;
    }
    Stop();

    return 1;
}










UINT8sxD_WriteReg(UINT8 Regis_Addr,UINT8 Data)
{


	returnsxD_I2C_WRITE(Regis_Addr,Data);

    return 1;
}

UINT8sxD_ReadReg(UINT8 Regis_Addr)
{
    UINT8 Data;



	Data =sxD_I2C_READ(Regis_Addr);

//	TRACE("end:%03d\n",   tmbuf.millitm);
    return Data;
}

UINT8sxD_I2C_WRITE(UINT8 Regis_Addr,UINT8 Data)
{
    UINT8 ret;
    UINT8 tryCount = I2C_TIMEOUT_COUNT;

    while(--tryCount) {
        ret = I2C_Write_1byte(I2C_DEV0_ADDRESS, Regis_Addr, Data);
        if(ret) break;
    }
    if(!tryCount) {
	SPRINTF(("sxD_I2C_WRITE error!\n"));	
		return 0;
    }

	return 1;
}

UINT8sxD_I2C_READ(UINT8 Regis_Addr)
{
    UINT8 ret;
	UINT8 dat;
    UINT8 tryCount = I2C_TIMEOUT_COUNT;

    while(--tryCount) {
	ret = I2C_Read_1byte(I2C_DEV0_ADDRESS, Regis_Addr, &dat);
        if(ret) break;
    }
    if(!tryCount) {
	//SPRINTF(("sxD_I2C_READ error!\n"));	
    }

	return dat;
}

UINT8sxD_I2C_NREAD(UINT8 Regis_Addr, UINT8 *buf, UINT8 n)
{
    UINT8 ret;
    UINT8 tryCount = I2C_TIMEOUT_COUNT;

    while(--tryCount) {
        ret = I2C_Read_nbyte(I2C_DEV0_ADDRESS, Regis_Addr, buf, n);
        if(ret) break;
    }
    if(!tryCount) {
	SPRINTF(("sxD_I2C_READ error!\n"));	
    }

    return ret;
}

UINT8sxD_I2C_NWRITE(UINT8 Regis_Addr, UINT8 *buf, UINT8 n)
{
    UINT8 ret;
    UINT8 tryCount = I2C_TIMEOUT_COUNT;

    while(--tryCount) {
        ret = I2C_Write_nbyte(I2C_DEV0_ADDRESS, Regis_Addr, buf, n);
        if(ret) break;
    }
    if(!tryCount) {
	    SPRINTF(("sxD_I2C_READ error!\n"));	
    }

    return ret;
}


/*************************************************************************************************************
                              end file
 ************************************************************************************************************/#include "sxdriver.h"
#include "sxio.h"

#include "common.h"

extern void _putc(unsigned char c);


#define SPRINTF(a) print_str(a)


/*****************************************************************************************************
** Name:      Msdelay()
** Function:  time delay
*****************************************************************************************************/

#define ACK			0
#define NACK			1

#define	DELAY_TIME	6
//#define	DELAY_TIME	100

void delay(UINT16 t) 
{ 
	while(t!=0) 
	  t--; 
} 



/****************************************************************
*     _____      _____________              ______________          ___________
* SCL      |____|             |____________|              .....____|
*
*     |Start|   |<--Read-->| |<--Write--->|                          |*STOP*|
* SDA ___      ________________             ______________              ________
*        |____|                MMMMMMMMMMMMM              .....________|
*
*
*****************************************************************/
// SCL:0, SDA:0
// SCL:H--H--L
// SDA:H--L--L
void Start(void)               
{ 
  SCL=1; 
  
  SDA=1; 
  delay(DELAY_TIME); 
  SDA=0; 
  delay(DELAY_TIME); 
  
  SCL=0; 
  delay(DELAY_TIME); 
}


// SCL:H--H--H
// SDA:L--H--H
void Stop(void)              
{
	SDA=0; 
	SCL=1; 
	delay(DELAY_TIME); 
	SDA=1; 
	delay(DELAY_TIME); 
	SCL=0; 
	delay(DELAY_TIME);
	SCL=1; 

}


// 0:ACK, 1:NACK(last byte)
void Send_ACK(UINT8 ack)
{
	SCL = 0;
	SDA = ack;
	//if(ack)		
	//	SDA = 0;
	//else
	//	SDA = 1;
	
	delay(DELAY_TIME); 
	SCL=1; 
	delay(DELAY_TIME); 
	SCL=0; 
	delay(DELAY_TIME); 
}




 

UINT8 Check_ACK(void) 
{ 
	UINT8	cnt;
	
	SDA = 1; 
	SCL = 1; 
	delay(DELAY_TIME); 
	
	for(cnt = 0; cnt< 100; cnt++)
	{
		if( SDA == 0)
			break;		// ack getted~
		delay(3); 	
	}

	SCL = 0; 
	delay(DELAY_TIME); 
	
	if (cnt >=100) // over time!
	  return 0; 

	return 1; 
} 






// SCL: Hi-->Lo == begin to write
void Write_Byte(UINT8 dat)
{
	UINT8 i; 
	
	for (i = 0; i < 8; i++)
	{
		if ((dat<<i) & 0x80) {
		  SDA = 1; 
		}
		else {
	     	  SDA = 0;
		}
		SCL = 1;
		delay(DELAY_TIME);
		SCL = 0;
		delay(DELAY_TIME);
	}

}


UINT8 Write_Byte_Check(UINT8 dat)
{
	Write_Byte(dat);
	if (!Check_ACK()) 
	{ 
		Stop();
		SPRINTF(("ACK err\n"));	
		return 0; 
	}
	//SPRINTF(("ACK OK!\n"));	
	return 1;
}





//	MSB->LSB
// SCL: Lo-->Hi == begin to read
UINT8 Read_Byte(void)
{
    UINT8 Data1=0x00;
    UINT8 j;

	SCL = 0;
	delay(10);
	SDA = 1;	// ready for input
  
	for (j = 0; j < 8; j++) 
	{ 
		delay(DELAY_TIME);
		SCL = 0;	
		delay(DELAY_TIME);
		SCL = 1;	// valid data
		delay(DELAY_TIME);
		
		Data1 <<= 1;
		
		if(SDA){
			Data1 += 1;
		}
	} 
	
	SCL = 0;

    return Data1;
}
 
/************************************************************************************************************
** Name: I2C_Write_1byte                         
** Funcation:write a data to a desired            
**           register through i2c bus 
** Description: Slave---------device address
**              Regis_Addr----register address
*************************************************************************************************************/
UINT8 I2C_Write_1byte(UINT8 Slave,UINT8 Regis_Addr,UINT8 dat)
{
    Start();
	
	if(Write_Byte_Check(Slave)==0)
		return 0;

	if(Write_Byte_Check(Regis_Addr)==0)
		return 0;

	if(Write_Byte_Check(dat)==0)
		return 0;

    Stop();
	
    return 1;
}
 	   
/***********************************************************************************************************
** Name: I2C_Read_1byte                          
** Function: Read a data from a desired register 
**           through i2c bus 
** Description: Slave---------device address
**              Regis_Addr----register address
************************************************************************************************************/
UINT8 I2C_Read_1byte(UINT8 Slave,UINT8 Regis_Addr, UINT8 *buff)
{ 
    UINT8 dat = 0x00;
    UINT8 temp;
    temp =Slave | 0x01;

        Start();

	//print_strhex("slave", Slave);
	//print_strhex("Regis_Addr", Regis_Addr);
	//print_strhex("temp", temp);	

	if(Write_Byte_Check(Slave)==0)
		return 0;

	if(Write_Byte_Check(Regis_Addr)==0)
		return 0;

	Stop();
	Start();

	if(Write_Byte_Check(temp)==0)
		return 0;

	*buff = Read_Byte();
	Send_ACK(NACK);

    Stop();

    return 1;
}

  /***********************************************************************************************************
  ** Name: I2C_Read_nbyte							
  ** Function: Read n data from a desired register	
  **		   through i2c bus 
  ** Description: Slave---------device address
  **			  Regis_Addr----register address
  ************************************************************************************************************/
  UINT8 I2C_Read_nbyte(UINT8 Slave,UINT8 Regis_Addr, UINT8 *buf, UINT8 n)
  { 
    UINT8 Data=0x00;
    UINT8 i;

    Start();
	if(Write_Byte_Check(Slave)==0)
		return 0;
	if(Write_Byte_Check(Regis_Addr)==0)
		return 0;
	
	Stop();

	// restart
	Start();
	if(Write_Byte_Check(Slave|0x01)==0)
		return 0;
	
	for(i=0; i<n-1; i++) {
		buf[i] = Read_Byte();
		Send_ACK(ACK);
	}
	buf[i] = Read_Byte();
	Send_ACK(NACK);

    Stop();
    return 1;
}



  /***********************************************************************************************************
	** Name: I2C_Write_nbyte				
	** Function: Write n bytes data to register 
	**			 through i2c bus 
	** Description: Slave---------device address
	**				Regis_Addr----register address
	************************************************************************************************************/
UINT8 I2C_Write_nbyte(UINT8 Slave,UINT8 Regis_Addr, UINT8 *buf, UINT8 n)
{ 
    UINT8 temp;
	UINT8 i;
    temp=Slave;


    Start();
	if(Write_Byte_Check(Slave)==0)
		return 0;
	if(Write_Byte_Check(Regis_Addr)==0)
		return 0;
	
    for(i=0; i<n; i++) {
		if(Write_Byte_Check(buf[i])==0)
			return 0;
    }
    Stop();

    return 1;
}










UINT8sxD_WriteReg(UINT8 Regis_Addr,UINT8 Data)
{


	returnsxD_I2C_WRITE(Regis_Addr,Data);

    return 1;
}

UINT8sxD_ReadReg(UINT8 Regis_Addr)
{
    UINT8 Data;



	Data =sxD_I2C_READ(Regis_Addr);

//	TRACE("end:%03d\n",   tmbuf.millitm);
    return Data;
}

UINT8sxD_I2C_WRITE(UINT8 Regis_Addr,UINT8 Data)
{
    UINT8 ret;
    UINT8 tryCount = I2C_TIMEOUT_COUNT;

    while(--tryCount) {
        ret = I2C_Write_1byte(I2C_DEV0_ADDRESS, Regis_Addr, Data);
        if(ret) break;
    }
    if(!tryCount) {
	SPRINTF(("sxD_I2C_WRITE error!\n"));	
		return 0;
    }

	return 1;
}

UINT8sxD_I2C_READ(UINT8 Regis_Addr)
{
    UINT8 ret;
	UINT8 dat;
    UINT8 tryCount = I2C_TIMEOUT_COUNT;

    while(--tryCount) {
	ret = I2C_Read_1byte(I2C_DEV0_ADDRESS, Regis_Addr, &dat);
        if(ret) break;
    }
    if(!tryCount) {
	//SPRINTF(("sxD_I2C_READ error!\n"));	
    }

	return dat;
}

UINT8sxD_I2C_NREAD(UINT8 Regis_Addr, UINT8 *buf, UINT8 n)
{
    UINT8 ret;
    UINT8 tryCount = I2C_TIMEOUT_COUNT;

    while(--tryCount) {
        ret = I2C_Read_nbyte(I2C_DEV0_ADDRESS, Regis_Addr, buf, n);
        if(ret) break;
    }
    if(!tryCount) {
	SPRINTF(("sxD_I2C_READ error!\n"));	
    }

    return ret;
}

UINT8sxD_I2C_NWRITE(UINT8 Regis_Addr, UINT8 *buf, UINT8 n)
{
    UINT8 ret;
    UINT8 tryCount = I2C_TIMEOUT_COUNT;

    while(--tryCount) {
        ret = I2C_Write_nbyte(I2C_DEV0_ADDRESS, Regis_Addr, buf, n);
        if(ret) break;
    }
    if(!tryCount) {
	    SPRINTF(("sxD_I2C_READ error!\n"));	
    }

    return ret;
}


/*************************************************************************************************************
                              end file
 ************************************************************************************************************/
